﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Abp.Domain.Repositories;
using Abp.Domain.Services;
using Abp.UI;

namespace DHJ.Cost.TreeStructure
{
    public class TreeBaseManager<TNode> : DomainService, ITreeBaseManager<TNode> where TNode : TreeNodeBase
    {
        protected readonly IRepository<TNode, long> NodeRepository;
        private const int SingleLevelIdLength = 16;
        private const string LevelSeparator = "-";

        public TreeBaseManager(IRepository<TNode, long> nodeRepository)
        {
            NodeRepository = nodeRepository;
        }

        /// <summary>
        /// 获取本节点下一层节点
        /// </summary>
        /// <returns></returns>
        public List<TNode> GetChildren(string nodeCode)
        {
            return NodeRepository.GetAllList(e =>
                e.NodeCode.StartsWith(nodeCode) && e.NodeCode.Length == nodeCode.Length + SingleLevelIdLength);
        }

        /// <summary>
        /// 获取本节点下所有层节点
        /// </summary>
        /// <returns></returns>
        public List<TNode> GetAllChildren(string nodeCode)
        {
            return NodeRepository.GetAllList(
                e => e.NodeCode.StartsWith(nodeCode) && e.NodeCode.Length > nodeCode.Length);
        }

        /// <summary>
        /// 获取本节点
        /// </summary>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        public TNode GetNode(long nodeId)
        {
            return NodeRepository.Get(nodeId);
        }

        /// <summary>
        /// 获取所有根节点
        /// </summary>
        /// <returns></returns>
        public List<TNode> GetAllRootNode()
        {
            return NodeRepository.GetAllList(e => e.NodeCode.Length == SingleLevelIdLength).ToList();
        }

        /// <summary>
        /// 插入一个根节点
        /// </summary>
        /// <param name="newNode"></param>
        /// <returns></returns>
        public TNode InsertNode(TNode newNode)
        {
            return NodeRepository.Insert(newNode);
        }

        /// <summary>
        /// 插入根节点组
        /// </summary>
        /// <param name="newNodes"></param>
        /// <returns></returns>
        public async Task InsertNodesAsync(List<TNode> newNodes)
        {
            foreach (var node in newNodes)
            {
                await NodeRepository.InsertAsync(node);
            }
        }

        /// <summary>
        /// 在指定节点下插入子节点
        /// </summary>
        /// <param name="newNode"></param>
        /// <param name="parentId"></param>
        /// <returns></returns>
        public TNode InsertNode(TNode newNode, long parentId)
        {
            if (NodeRepository.Get(parentId) == null || newNode.NodeCode.Length > SingleLevelIdLength)
                throw new UserFriendlyException("添加节点失败，请刷新后重试！");

            var parentNode = GetNode(parentId);
            newNode.NodeCode = string.Join(LevelSeparator, parentNode.NodeCode, newNode.NodeCode);
            var nodes = NodeRepository.Insert(newNode);
            return nodes;
        }

        /// <summary>
        /// 在指定节点下插入子节点组
        /// </summary>
        /// <returns></returns>
        public async Task InsertNodesAsync(List<TNode> newNodes, string parentCode, long parentId)
        {
            foreach (var node in newNodes)
            {
                if (NodeRepository.Get(parentId) == null || node.NodeCode.Length > SingleLevelIdLength)
                    throw new UserFriendlyException("添加节点失败，请刷新后重试！");

                node.NodeCode = string.Join(LevelSeparator, parentCode, node.NodeCode);
                await NodeRepository.InsertAsync(node);
            }
        }

        /// <summary>
        /// 删除节点，以及节点下所有子节点！！！！！小心
        /// </summary>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        public async Task DelTree(long nodeId)
        {
            var node = GetNode(nodeId);
            await NodeRepository.DeleteAsync(e => e.NodeCode.StartsWith(node.NodeCode));
        }

        ///// <summary>
        ///// 删除本节点
        ///// </summary>
        ///// <param name="node"></param>
        ///// <returns></returns>
        public async Task DelNode(long nodeId)
        {
            //删除本节点
            await NodeRepository.DeleteAsync(nodeId);
            var node = GetNode(nodeId);
            //修改节点下属所有节点ID（前半部分）
            var allChildrenNodes = GetAllChildren(node.NodeCode);

            foreach (var n in allChildrenNodes)
            {
                n.NodeCode = n.NodeCode.TrimStart((string.Concat(nodeId, LevelSeparator)).ToCharArray());
            }
        }

        ///// <summary>
        ///// 移动节点
        ///// </summary>
        ///// <param name="nodeId"></param>
        ///// <param name="targetNodeId"></param>
        ///// <returns></returns>
        public void MoveNode(long nodeId, long targetNodeId)
        {
            var currentNode = GetNode(nodeId);
            var targetNode = GetNode(targetNodeId);
            var changeNodes = GetAllChildren(currentNode.NodeCode);

            if (NodeRepository.Get(targetNodeId) == null)
            {
                throw new UserFriendlyException("移动目的地不存在，请刷新后重试！");
            }

            var nodeLevels = currentNode.NodeCode.Split(LevelSeparator.ToCharArray());
            var currentParentNodeCode = string.Join(LevelSeparator, nodeLevels.Take(nodeLevels.Length - 1));

            foreach (var n in changeNodes)
            {
                n.NodeCode =
                    n.NodeCode.TrimStart((string.Concat(currentParentNodeCode, LevelSeparator)).ToCharArray());
                //添加新的信息
                n.NodeCode = string.Join(LevelSeparator, targetNode.NodeCode, n.NodeCode);
            }
        }

        Task ITreeBaseManager<TNode>.MoveNode(long nodeId, long targetNodeId)
        {
            throw new NotImplementedException();
        }
    }
}